package com.jy.api.controller.pay;

import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.PayTypeEnum;
import com.jy.api.enums.RechargeEnum;
import com.jy.api.pay.result.PayResult;
import com.jy.api.service.*;
import com.jy.api.signUpReq.ScanCodeSignUpReq;
import com.jy.api.util.IpUtils;
import com.jy.api.util.UuidUtil;
import com.jy.api.util.XmlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by lihu on 2017/10/7.
 */
@Slf4j
@RestController
@RequestMapping(value = "v1/pay", produces = "application/json;charset=utf-8")
public class PayController {


    @Autowired
    OrderDao orderDao;

    @Autowired
    PayService payService;

    @Autowired
    StoreDao storeDao;

    @Autowired
    PaymentService paymentService;

    @Autowired
    EmployeeDao employeeDao;


    @Autowired
    WebRechargeDao webRechargeDao;

    @Autowired
    WorkShiftDao workShiftDao;

    @Autowired
    WebRechargeService webRechargeService;


    @Autowired
    OrderService orderService;

    @Autowired
    StoreOrderService storeOrderService;


    /**
     * 支付回调地址
     *
     * @param xml
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/callBack")
    public ResponseEntity callBack(@RequestBody String xml) {
        log.info("Received payment result notify, the content is:{}", xml);
        try {
            paymentService.handlePaymentNotify(xml);
            return ResponseEntity.ok("success");
        } catch (Exception e) {
            log.error("Fail to handle payment notify", e);
            return ResponseEntity.ok("fail");
        }
    }

    /**
     * 用于店铺支付回调
     *
     * @param result
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "store/callBack")
    public ResponseEntity storeCallBack(@RequestBody String result) {
        log.info("storeCallBack is info result:{} ", result);
        PayResult payResult = XmlUtils.fromXML(result, PayResult.class);
        try {
            if (payResult.successCallBack()) {
                storeOrderService.handleStoreOrder(payResult);
            }
        } catch (Exception ex) {
            log.error("storeCallBack pay fail:{}", payResult);
        }
        return new ResponseEntity("isPaymentSuccess", HttpStatus.OK);
    }


    /**
     * 用于店铺充值回调回调
     *
     * @param result
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "recharge/callBack")
    public ResponseEntity rechargeCallBack(@RequestBody String result) {
        log.info("storeCallBack is info result:{} ", result);
        PayResult payResult = XmlUtils.fromXML(result, PayResult.class);
        try {
            if (payResult.successCallBack()) {
                webRechargeService.updateWebRecharge(payResult);
            }
        } catch (Exception ex) {
            log.error("storeCallBack pay fail:{}", payResult);
        }
        return new ResponseEntity("isPaymentSuccess", HttpStatus.OK);
    }

    /**
     * 用于二维码支付订单结果查询查询
     *
     * @param orderId
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "/scan-code/query")
    public ResponseEntity payScanQuery(@RequestParam(name = "orderId") String orderId) {
        Order order = orderDao.findOne(orderId);

        //如果订单状态已更改
        if (OrderStatus.FINISHED == order.getStatus() || OrderStatus.UNFINISHED == order.getStatus()) {
            return new ResponseEntity(HttpStatus.OK);
        } else if (OrderStatus.NOTSURE == order.getStatus()) {
            return new ResponseEntity(HttpStatus.ACCEPTED);
        } else {
            return new ResponseEntity("支付失败！请核实！", HttpStatus.BAD_REQUEST);
        }

    }

    /**
     * 订单查询接口
     *
     * @param orderId
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "/micropay/query")
    public ResponseEntity payCardQuery(@RequestParam(name = "orderId") String orderId) {
        // // TODO: 2018/8/28 订单查询接口可以通用，不需要区分刷卡支付还是扫码支付，甚至不需要区分在线支付和现金支付
        Order order = orderDao.findOne(orderId);
        if (OrderStatus.FINISHED == order.getStatus() || OrderStatus.UNFINISHED == order.getStatus()) {
            // 支付成功
            return new ResponseEntity(HttpStatus.OK);
        } else if (OrderStatus.NOTSURE == order.getStatus()) {
            // 支付中
            return new ResponseEntity(HttpStatus.ACCEPTED);
        } else if (order.getStatus().equals(OrderStatus.FAIL)) {
            // 支付失败
            return new ResponseEntity("支付失败，请与顾客确认", HttpStatus.BAD_REQUEST);
        } else if (order.getStatus().equals(OrderStatus.INIT)) {
            Order newOrder = new Order(order);
            order.setStatus(OrderStatus.CANCELED);
            order.setEnabled(false);
            orderService.saveOrder(newOrder);
            orderService.saveOrder(order);
            return new ResponseEntity("支付失败，请重新进行支付！", HttpStatus.BAD_REQUEST);
        } else {
            throw new RuntimeException("支付结果未知，请稍后在订单列表中查看");
        }
    }

    /**
     * 微信公众号支付初始化请求参数接口（？？？）
     *
     * @param orderId
     * @param request
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = "/web-pay")
    public ResponseEntity webPay(@RequestParam(name = "orderId") String orderId,
                                 @RequestParam(name = "openId") String openId,
                                 @RequestParam(name = "tableNo", defaultValue = "") String tableNo,
                                 @RequestParam(name = "phone", defaultValue = "") String phone,
                                 @RequestParam(name = "notes", defaultValue = "") String notes,
                                 HttpServletRequest request) {
        Map<String, Object> orderData = new HashMap<>();
        orderData.put("notes", notes);
        orderData.put("tableNo", tableNo);
        orderService.patch(orderId, orderData);

        SwiftPassJSPayResult result = paymentService.jsPay(orderId, openId);
        if (result.isSuccess()) {
            return new ResponseEntity(result.getPayInfo(), HttpStatus.OK);
        } else {
            return new ResponseEntity(result.getErrMsg(), HttpStatus.BAD_REQUEST);
        }
    }


    /**
     * 店铺收费
     *
     * @param type
     * @param request
     * @return
     */
    @Transactional
    @RequestMapping(method = RequestMethod.GET, value = "/web/scan-code")
    public ResponseEntity scanCode(@RequestParam(name = "storeId") String storeId,
                                   @RequestParam(name = "rechargeType") RechargeEnum rechargeEnum,
                                   @RequestParam(name = "type", defaultValue = "true") boolean type,
                                   HttpServletRequest request) {

        Store store = storeDao.findOne(storeId);
        if (store == null) {
            return new ResponseEntity("店铺信息不存在！", HttpStatus.BAD_REQUEST);
        }
        String checkResult = store.checkRechargeLevel(rechargeEnum);
        if (StringUtils.isNotBlank(checkResult)) {
            return new ResponseEntity(checkResult, HttpStatus.BAD_REQUEST);
        }

        //换算充值金额
        int amount = 0;
        switch (rechargeEnum) {
            case UPGRADE:
                amount = 200000;
                break;
            case THREE_LEVEL:
                amount = 320000;
                break;
            case SECOND_LEVEL:
                amount = 120000;
                break;
        }
        String payType = null;
        PaymentChannel channel = null;
        if (type) {
            payType = PayTypeEnum.PAY_ALIPAY_NATIVE.getCode();
            channel = PaymentChannel.ALIPAY;
        } else {
            payType = PayTypeEnum.PAY_WX_NATIVE.getCode();
            channel = PaymentChannel.WECHATPAY;
        }

        try {
            String uuId = UuidUtil.getUuid();
            PayResult scanCodeResult = payService.MyQRCode(IpUtils.getIpAddr(request),
                    payType, uuId, amount);
            if (StringUtils.equals(scanCodeResult.getStatus(), "0") &&
                    StringUtils.equals(scanCodeResult.getResultCode(), "0")) {
                WebRecharge webRecharge = new WebRecharge(uuId, storeId, channel, amount);
                webRechargeDao.save(webRecharge);
                Map map = new HashMap();
                map.put("url", scanCodeResult.getCodeImgUrl());
                map.put("id", webRecharge.getId());
                return new ResponseEntity(map, HttpStatus.OK);
            } else {
                log.error("scanCode  is error :{}", scanCodeResult);
                return new ResponseEntity(scanCodeResult.getErrMsg()
                        != null ? scanCodeResult.getErrMsg() : scanCodeResult.getMessage(), HttpStatus.BAD_REQUEST);
            }
        } catch (Exception ex) {
            log.error("scanCode  is error==> storeId:{}", storeId, ex);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 店铺充值查询轮询接口
     *
     * @param id
     * @return
     */
    @Transactional
    @RequestMapping(method = RequestMethod.GET, value = "/scan-code/web-query")
    public ResponseEntity webScanQuery(@RequestParam(name = "id") String id) {
        try {
            WebRecharge webRecharge = webRechargeDao.findOne(id);
            if (webRecharge == null) {
                return new ResponseEntity("充值信息不存在！", HttpStatus.BAD_REQUEST);
            }
            if (webRecharge.getStatus() == PaymentStatus.SUCCESS) {
                return new ResponseEntity(HttpStatus.OK);
            } else {
                return new ResponseEntity(HttpStatus.ACCEPTED);
            }
        } catch (Exception ex) {
            log.error("payScanQuery  is error==> id{}", id, ex);
            return new ResponseEntity("支付失败！请切换支付方式！", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 扫码支付统一下单接口
     *
     * @param scanCodeSignUpReq
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = "/scan-code")
    public ResponseEntity getScanCode(@Valid @RequestBody ScanCodeSignUpReq scanCodeSignUpReq) {
        Map<String, Object> orderData = new HashMap<>();
        orderData.put("notes", scanCodeSignUpReq.getNotes());
        orderData.put("tableNo", scanCodeSignUpReq.getTableNo());
        orderService.patch(scanCodeSignUpReq.getOrderId(), orderData);

        PayTypeEnum payType = scanCodeSignUpReq.isType() ? PayTypeEnum.PAY_ALIPAY_NATIVE : PayTypeEnum.PAY_WX_NATIVE;

        Order order = orderDao.findOne(scanCodeSignUpReq.getOrderId());
        Store store = storeDao.findOne(order.getStoreId());
        if (store.getPayMode() == PayMode.CASHIER) {
            PaymentChannel channel = store.getChannel(scanCodeSignUpReq.isType());
            //校验开班信息
            WorkShift workShift = workShiftDao.findByStoreIdAndClosed(order.getStoreId(), false);
            if (workShift == null) {
                return new ResponseEntity("无开班信息！请等待收银台开班！", HttpStatus.BAD_REQUEST);
            }
            Employee employee = employeeDao.findByUsernameAndEnabled(workShift.getOperatorId(), true).get(0);
            Map<String, String> map = new HashMap();
            map.put("url", getCashier(employee, channel));
            map.put("payMode", "CASHIER");
            return ResponseEntity.ok(map);
        } else {
            SwiftPassQRCodePayResult result = paymentService.qrCodePay(scanCodeSignUpReq.getOrderId(), payType);
            Map<String, String> map = new HashMap();
            if (result.isSuccess()) {
                map.put("payMode", "THIRD_PARTY");
                map.put("url", result.getCodeImgURL());
                return ResponseEntity.ok(map);
            } else {
                return ResponseEntity.badRequest().body("该订单已取消，请重新生成订单进行支付！");
            }
        }
    }

    /**
     * 获取非第三方支付二维码信息
     *
     * @return
     */
    private String getCashier(Employee employee, PaymentChannel channel) {
        String url = null;
        if (channel == PaymentChannel.ALIPAY_CASH) {
            url = employee.getAliPayUrl();
        }
        if (channel == PaymentChannel.WECHATPAY_CASH) {
            url = employee.getWechatPayUrl();
        }
        return url;
    }
}
